﻿using System;
using System.Collections.Generic;
using System.Text;
/*
namespace ycdlib
{
	/// <summary>
	/// 解析する
	/// </summary>
	public unsafe class Parser
	{
		/// <summary>
		/// 解析する
		/// </summary>
		/// <param name="s"></param>
		/// <returns></returns>
		static public YCDocument Parse( string s )
		{
			YCReaderSetting readerSetting = new YCReaderSetting();
			YCDocument result = null;
			char[] C = s.ToCharArray();
			result = Parse( C, C.Length, readerSetting );
			return result;
		}


		/// <summary>
		/// 解析する
		/// </summary>
		/// <param name="s"></param>
		/// <param name="readerSetting"></param>
		/// <returns></returns>
		static public YCDocument Parse( string s, YCReaderSetting readerSetting )
		{
			YCDocument result = null;
			char[] C = s.ToCharArray();
			result = Parse( C, C.Length, readerSetting );
			return result;
		}


		/// <summary>
		/// 解析する
		/// </summary>
		/// <param name="str"></param>
		/// <param name="length"></param>
		/// <param name="readerSetting"></param>
		/// <returns></returns>
		static public YCDocument Parse( char[] str, int length, YCReaderSetting readerSetting )
		{
			Parser P = new Parser();
			P.parse( str, length, readerSetting );
			return P.doc;
		}


		#region フィールド

		YCReaderSetting setting;
		YCDocument doc;
		int currLine;
		int currCol;
		char[] B;
		char* C;
		int size;
		int ptr;

		#endregion


		/// <summary>
		/// コンストラクタは公開しない
		/// </summary>
		internal Parser ()
		{
			doc = null;
			currLine = 0;
			currCol = 0;
			B = null;
			size = 0;
			ptr = 0;
		}


		/// <summary>
		/// 解析する。
		/// </summary>
		/// <param name="str">文字配列</param>
		/// <param name="length">文字配列の長さ</param>
		private void parse( char[] str, int length, YCReaderSetting readerSetting )
		{
			doc = new YCDocument();
			setting = readerSetting;
			currLine = 1;
			currCol = 1;
			B = str;
			fixed( char* c = str )
			{
				C = c;
				size = length;
				ptr = 0;
				do
				{
					if( !skipWhiteSpace() ) break;
					readNode( null );
				}while( ptr < size );
			}
		}


		/// <summary>
		/// ノードを読み込む
		/// </summary>
		/// <returns></returns>
		private bool readNode ( YCNode parentNode )
		{
			bool result = false;
			
			//	ホワイトスペースをとばして
			if( !skipWhiteSpace() ) throw new YCDParseException();

			//	型名を読み込む
			string tName = readType();
//System.Diagnostics.Debug.WriteLine("tname = " + tName);

			//	ホワイトスペースをとばして
			if( !skipWhiteSpace() ) throw new YCDParseException();

			//	名前を読み込む
			string name = readName();
//System.Diagnostics.Debug.WriteLine("name = " + name);

			//	ＩＤを読み込む
			string id = readID();
//System.Diagnostics.Debug.WriteLine("id = " + id);

			//	イコールを探す
			if( !findEqualChar() ) throw new YCDParseException();

			//	現在のptrが＝を指しているので次に進める
			++ptr;
			char c = B[ptr];
			if( ptr==size ) throw new YCDParseException();

			//	空白を飛ばす
			if( !skipWhiteSpace() ) throw new YCDParseException();


			YCNode __newNode = null;
			ValueParse vp = null;
			if( setting.TryGetParser( tName, out vp ) )
			{
				__newNode = vp( parentNode, tName, name, id, this );
			}else
			{
				__newNode = YCNodeAnother.Parse( parentNode, tName, name, id, this );
			}


				if( parentNode == null )
				{
					if( doc.Children==null ) doc.Children = new List<YCNode>();
					doc.Children.Add( __newNode );
				}else
				{
					parentNode.AddChild( __newNode );
				}

				if( ptr < size )
				{
					c = B[ptr];
					if( c==';' || c=='}' ) ++ptr;
				}

			return result;
		}


		/// <summary>
		/// 値を読み込む
		/// </summary>
		/// <returns></returns>
		public object readValue ()
		{
			char c = B[ptr];

			if( c=='-' || c=='+' || c=='.' || ('0'<=c && c<='9') )
			{
				return readNumeric();
			}else if( c=='{' )
			{
				return readList();
			}else if( c=='"' )
			{
				return readString();
			}
			throw new YCDParseException();
		}


		/// <summary>
		/// 文字列を読み込む。ptrは"にいる
		/// </summary>
		/// <returns></returns>
		public string readString ()
		{
			if( B[ptr] != '"' ) throw new YCDParseException();
			++ptr;
			if( ptr>size ) throw new YCDParseException();

			StringBuilder sb = new StringBuilder();
			int begin = ptr;
			char c = B[ptr];
			while( true )
			{
				if( c=='\\' )
				{
					++ptr;
					if( ptr==size ) throw new YCDParseException();
					if( B[ptr]=='\\' )
					{
						sb.Append( B, begin, ptr-begin-1 ).Append( '\\' );
						begin = ptr + 1;
					} else if( B[ptr]=='"' )
					{
						sb.Append( B, begin, ptr-begin-1 ).Append( '"' );
						begin = ptr + 1;
					} else if( B[ptr]=='n' )
					{
						sb.Append( B, begin, ptr-begin-1 ).Append( '\n' );
						begin = ptr + 1;
					} else if( B[ptr]=='r' )
					{
						sb.Append( B, begin, ptr-begin-1 ).Append( '\r' );
						begin = ptr + 1;
					}
				}else if( c=='"' )
				{
					++ptr;
					if( ptr==size ) throw new YCDParseException();
					if( B[ptr]=='"' )
					{
						sb.Append( B, begin, ptr-begin-1 ).Append( '"' );
						begin = ptr + 1;
					} else
					{
						sb.Append( B, begin, ptr-begin-1 );
						break;
					}
				}
				++ptr;
				if( ptr==size ) throw new YCDParseException();
				c = B[ptr];
			}
			return sb.ToString();
		}


		/// <summary>
		/// 数値と思しき物体を読み込む。ptrは先頭文字
		/// </summary>
		/// <returns></returns>
		public object readNumeric ()
		{
			//	先頭文字は、＋、－、．、０～９の判定でここにきている。
			char c = B[ptr];

			int begin = ptr;
			bool isFloat = false;

			++ptr;
			if( ptr == size ) throw new YCDParseException();

			//	先頭文字が記号であった場合、2文字目が必ず必要
			if( c=='+' || c=='-' || c=='.' )
			{
				if( c=='.' ) isFloat = true;
				c = B[ptr];
				if( c<'0' || '9'<c ) throw new YCDParseException();
			}

			c = B[ptr];
			//	2文字目以降。数字、ドット、カンマが許容されるのか？
			while(true)
			{
				c = B[ptr];
				if( c=='.' || c==',' || ('0'<=c && c<='9') )
				{
					if( c=='.' ) isFloat = true;
					++ptr;
					if( ptr == size ) throw new YCDParseException();
				}else
				{
					break;
				}
			}

			object r = null;
			string s = new string( B, begin, ptr-begin );
			s.Replace( ",", "" );
			if( isFloat )
			{
				r = Double.Parse( s );
			}else
			{
				r = Int64.Parse( s );
			}
			return r;
		}


		/// <summary>
		/// 32bit整数を読み込む
		/// </summary>
		/// <returns></returns>
		public int readInteger ()
		{
			//	先頭文字は、＋、－、．、０～９の判定でここにきている。
			char c = B[ptr];

			int begin = ptr;

			++ptr;
			if( ptr == size ) throw new YCDParseException();

			//	先頭文字が記号であった場合、2文字目が必ず必要
			if( c=='+' || c=='-' )
			{
				c = B[ptr];
				if( c<'0' || '9'<c ) throw new YCDParseException();
			}

			c = B[ptr];
			//	2文字目以降。数字、ドット、カンマが許容されるのか？
			while(true)
			{
				c = B[ptr];
				if( c==',' || ('0'<=c && c<='9') )
				{
					++ptr;
					if( ptr == size ) throw new YCDParseException();
				}else
				{
					break;
				}
			}

			string s = new string( B, begin, ptr-begin );
			return Int32.Parse( s.Replace( ",", "" ) );
		}


		/// <summary>
		/// 64bit整数を読み込む
		/// </summary>
		/// <returns></returns>
		public long readLong ()
		{
			//	先頭文字は、＋、－、．、０～９の判定でここにきている。
			char c = B[ptr];

			int begin = ptr;

			++ptr;
			if( ptr == size ) throw new YCDParseException();

			//	先頭文字が記号であった場合、2文字目が必ず必要
			if( c=='+' || c=='-' )
			{
				c = B[ptr];
				if( c<'0' || '9'<c ) throw new YCDParseException();
			}

			c = B[ptr];
			//	2文字目以降。数字、ドット、カンマが許容されるのか？
			while(true)
			{
				c = B[ptr];
				if( c==',' || ('0'<=c && c<='9') )
				{
					++ptr;
					if( ptr == size ) throw new YCDParseException();
				}else
				{
					break;
				}
			}

			string s = new string( B, begin, ptr-begin );
			return Int64.Parse( s.Replace( ",", "" ) );
		}


		/// <summary>
		/// 浮動小数値を読み込む
		/// </summary>
		/// <returns></returns>
		public object readFloat ()
		{
			//	先頭文字は、＋、－、．、０～９の判定でここにきている。
			char c = B[ptr];

			int begin = ptr;

			++ptr;
			if( ptr == size ) throw new YCDParseException();

			//	先頭文字が記号であった場合、2文字目が必ず必要
			if( c=='+' || c=='-' || c=='.' )
			{
				c = B[ptr];
				if( c<'0' || '9'<c ) throw new YCDParseException();
			}

			c = B[ptr];
			//	2文字目以降。数字、ドット、カンマが許容されるのか？
			while(true)
			{
				c = B[ptr];
				if( c=='.' || c==',' || ('0'<=c && c<='9') )
				{
					++ptr;
					if( ptr == size ) throw new YCDParseException();
				}else
				{
					break;
				}
			}

			string s = new string( B, begin, ptr-begin );
			return Double.Parse( s.Replace( ",", "" ) );
		}


		/// <summary>
		/// たぶんリストであろうものを読み込む。ptrは{
		/// </summary>
		/// <returns></returns>
		private object readList ()
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// イコール文字を探す
		/// </summary>
		/// <returns></returns>
		private bool findEqualChar()
		{
			char c = B[ptr];
			while( c!='=' )
			{
				++ptr;
				if( ptr==size ) return false;
				c = B[ptr];
				if( c=='\n' ) { ++currLine; currCol=1; }
				else { ++currCol; }
			}
			return true;
		}


		private string readID ()
		{
			char c = B[ptr];
			if( c!=':' ) return null;

			++ptr;
			if( ptr==size ) throw new YCDParseException();

			if( !skipWhiteSpace() ) throw new YCDParseException();

			int begin = ptr;
			if( ('A'<c && c<'Z') || c=='_' || ('a'<c && c<'z') )
			{
				++ptr;
				if( ptr == size ) return null;

				c = B[ptr];
				while( ' ' < c && c!='=' )
				{
					if( ('0'>c || c>'9') && ('A'>c || c>'Z') && c!='_' && ('a'>c || c>'z') )
					{
						return null;
					}
					++ptr;
					if( ptr == size ) return null;
				}
			}else
			{
				return null;
			}
			return new string( B, begin, ptr-begin );
		}


		/// <summary>
		/// 名前を読み込む
		/// </summary>
		/// <returns>型名の文字列</returns>
		internal string readName ()
		{
			char c = B[ptr];
			int begin = ptr;
			if( ('A'<=c && c<='Z') || c=='_' || ('a'<=c && c<='z') )
			{
				++ptr;
				if( ptr == size ) return null;

				c = B[ptr];
				while( ' ' < c && c!=':' )
				{
					if( ('0'>c || c>'9') && ('A'>c || c>'Z') && c!='_' && ('a'>c || c>'z') )
					{
						return null;
					}
					++ptr;
					if( ptr == size ) return null;
				}
			}else
			{
				return null;
			}
			return new string( B, begin, ptr-begin );
		}


		/// <summary>
		/// 型名を読み込む
		/// </summary>
		/// <returns>型名の文字列</returns>
		internal string readType ()
		{
			char c = B[ptr];
			int begin = ptr;
			if( ('A'<c && c<'Z') || c=='_' || ('a'<c && c<'z') )
			{
				++ptr;
				if( ptr == size ) return null;

				c = B[ptr];
				while( ' ' < c )
				{
					if( ('0'>c || c>'9') && ('A'>c || c>'Z') && c!='_' && ('a'>c || c>'z') )
					{
						return null;
					}
					++ptr;
					if( ptr == size ) return null;
					c = B[ptr];
				}
			}else
			{
				return null;
			}
			return new string( B, begin, ptr-begin );
		}


		/// <summary>
		/// 空白をスキップする
		/// </summary>
		/// <returns></returns>
		internal bool skipWhiteSpace()
		{
			char c = B[ptr];
			while( c<=' ' )
			{
				++ptr;
				if( ptr==size ) return false;
				c = B[ptr];
				if( c=='\n' ) { ++currLine; currCol=1; }
				else { ++currCol; }
			}
			return true;
		}
	}
}
*/